package cn._2dland.websocket.io;

import java.io.IOException;
import java.io.OutputStream;

import cn._2dland.websocket.model.message.BinaryMessage;
import cn._2dland.websocket.model.message.ControlMessage;
import cn._2dland.websocket.model.message.Message;
import cn._2dland.websocket.model.message.TextMessage;

/**
 * for hybi ver. 0.0~7.0
 * 
 * @author deadblue
 */
public class MessageOutputStreamV00 extends MessageOutputStream {

	public MessageOutputStreamV00(OutputStream out) {
		super(out);
	}

	@Override
	public void writeMessage(Message msg) throws IOException {
		// 分类型写入
		if(msg instanceof ControlMessage) {
			writeControlMessage((ControlMessage) msg);
		} else if(msg instanceof BinaryMessage) {
			writeBinaryMessage((BinaryMessage) msg);
		} else if(msg instanceof TextMessage) {
			writeTextMessage((TextMessage) msg);
		}
	}

	/**
	 * 写入控制报文
	 * v00只有关闭报文
	 * 
	 * @param msg
	 * @throws IOException
	 */
	private void writeControlMessage(ControlMessage msg) throws IOException {
		// 非关闭报文则跳过
		if(msg.getCommand() != ControlMessage.CLOSE) {
			return;
		}

		// 写入关闭报文
		out.write(0xff);
	}

	/**
	 * 写入二进制报文
	 * 
	 * @param msg
	 * @throws IOException
	 */
	private void writeBinaryMessage(BinaryMessage msg) throws IOException {
		// 获取数据
		byte[] data = msg.getBinary();

		// 数据长度
		long length = data.length;
		// 长度的二进制位数
		int bitLength = (int) Math.floor(Math.log(length) / Math.log(2)) + 1;
		// 存储长度所用的字节数
		int byteCount = (int) Math.ceil(bitLength / 7.0);
		// 依次写入输出流
		for(int i = byteCount - 1 ; i >= 0; i--) {
			int b = (i == 0) ? 0x00 : 0x80;
			b |= (length >> (i * 7)) & 0x7f;
			out.write(b);
		}
		
		// 写入数据
		out.write(data);
	}

	/**
	 * 写入文本报文
	 * 
	 * @param msg
	 * @throws IOException
	 */
	private void writeTextMessage(TextMessage msg) throws IOException {
		String text = msg.getText();

		// 写入文本
		out.write(0x00);
		out.write(text.getBytes("utf-8"));
		out.write(0xff);
	}

}
